'''
不可修改
'''
import socket
import threading
import json

class server:
    '''负责接收message并保存在self.msg中，同时使用self.meg_from_client_id记录消息来源'''
    def __init__(self, get_message_from_server, host='::', port=65432):
        print('initiate')
        self.get_message_from_server = get_message_from_server
        self.host = host
        self.port = port
        self.clients = []  # 格式: {client_id: {"conn": 连接对象, "addr": ip地址, "id": 在服务器中的id}}
        self.lock = threading.Lock()
        self.next_client_id = 0

    def start(self):
        '''启动服务器'''
        with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
            s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)  # 允许 IPv4/IPv6 双栈
            s.bind((self.host, self.port))
            s.listen()
            print(f"服务器已启动，监听 {self.host}:{self.port}...")

            # 监听并处理进入服务器的客户端
            while True:
                conn, addr = s.accept()
                client_id = self.next_client_id
                self.next_client_id += 1
                print(f"有新客户端进入服务器，客户端id为{client_id}")
                threading.Thread(target=self.handle_client, args=(conn, addr, client_id)).start()

    def handle_client(self, conn, addr, client_id):
        """处理客户端连接"""
        with self.lock:
            self.clients.append({"conn": conn, "addr": addr, "id": client_id})
        
        buffer = ""
        try:
            while True:
                data = conn.recv(1024).decode()
                buffer += data  # 数据存入缓冲区
                # 按分隔符分割消息
                while '\n' in buffer:
                    line, buffer = buffer.split('\n', 1)  # 分割出第一条完整消息
                    if line:
                        with self.lock:
                            self.get_message_from_server(json.loads(line), client_id)
            pass
        finally:
            with self.lock:
                self.remove_client(client_id)
                conn.close()
                print(f"编号为{client_id}的客户端已退出服务器")

    def remove_client(self, client_id):
        """移除客户端"""
        with self.lock:
            if client_id in self.clients:
                del self.clients[client_id]

    def send_message_to_client(self, msg, client_id):
        if self.clients[client_id]["conn"] == None:
            return
        self.clients[client_id]["conn"].sendall(json.dumps(msg).encode()+ b'\n')

    def send_message_to_all(self, msg):
        for client in self.clients:
            client["conn"].sendall(json.dumps(msg).encode()+ b'\n')

    def get_message(self):# 获取消息以及发送消息的客户端的id
        return self.msg, self.msg_from_client_id
    
    def get_client_by_id(self, id):
        '''根据客户端在服务器中的编号获取该客户端信息'''
        target_client = [c for c in self.clients if c['id'] == id]
        if target_client == None:
            return None
        else:
            return target_client[0]

    def get_client_by_addr(self, addr):
        '''根据客户端的ip地址获取该客户端信息'''
        target_client = [c for c in self.clients if c['addr'] == addr]
        if target_client == None:
            return None
        else:
            return target_client[0]
